use std::str::FromStr;

#[derive(Debug, PartialEq)]
struct Point {
    x: i32,
    y: i32,
}

#[derive(Debug, PartialEq)]
struct ParsePointError;

impl FromStr for Point {
    type Err = ParsePointError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let (x, y) = s
            .strip_prefix('(')
            .and_then(|s| s.strip_suffix(')'))
            .and_then(|s| s.split_once(','))
            .ok_or(ParsePointError)?;

        let x_fromstr = x.parse::<i32>().map_err(|_| ParsePointError)?;
        let y_fromstr = y.parse::<i32>().map_err(|_| ParsePointError)?;

        Ok(Point {
            x: x_fromstr,
            y: y_fromstr,
        })
    }
}

fn run_tests() -> Result<(), ParsePointError> {
    // 正确输入
    assert_eq!(Point::from_str("(1,2)")?, Point { x: 1, y: 2 });
    assert_eq!(Point::from_str("(0,-5)")?, Point { x: 0, y: -5 });
    assert_eq!(Point::from_str("(-3, 4)")?, Point { x: -3, y: 4 });
    assert_eq!(Point::from_str("( 10 , 20 )")?, Point { x: 10, y: 20 });

    // 通过 .parse() 调用
    assert_eq!("(1,2)".parse::<Point>()?, Point { x: 1, y: 2 });

    // 错误输入：应返回 Err
    assert!(Point::from_str("").is_err());
    assert!(Point::from_str("1,2").is_err());
    assert!(Point::from_str("(1,2").is_err());
    assert!(Point::from_str("1,2)").is_err());
    assert!(Point::from_str("(1 2)").is_err());
    assert!(Point::from_str("(1,,2)").is_err());
    assert!(Point::from_str("(a,b)").is_err());
    assert!(Point::from_str("(1,)").is_err());
    assert!(Point::from_str("(,2)").is_err());

    Ok(())
}

fn main() {
    match run_tests() {
        Ok(()) => println!("✅ 所有集成测试通过！"),
        Err(e) => {
            eprintln!("❌ 测试失败: {:?}", e);
            std::process::exit(1);
        }
    }
}
